/**
 * A class for working with obtaining data values from an OCSS comma separated
 * value text file.
 */
package us.gaaoc.framework.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import us.gaaoc.framework.dao.ModelFacade;
import us.gaaoc.framework.dao.ModelFacadeHibernate;
import us.gaaoc.framework.model.Address;
import us.gaaoc.framework.model.AddressCategory;
import us.gaaoc.framework.model.AddressType;
import us.gaaoc.framework.model.Person;
import us.gaaoc.framework.model.PersonAddress;
import us.gaaoc.framework.util.validators.NameValidator;
import us.gaje.ocss.stars.DataFile;

/**
 * @author Michael Alexandrou May 11th, 2007 Parsing a text file Utility Class
 */

public class ValidatingTextFile {

	private static Logger LOG = Logger.getLogger(ValidatingTextFile.class);
	
	private Person cusPerson;
	private PersonAddress cusPersonAddress;
	private Address cusAddress;
	private Person nonCusPerson;
	private PersonAddress nonCusPersonAddress;
	private Address nonCusAddress;
	private List<Person> initiatingPartyPersonsList = new ArrayList<Person>();
	private List<PersonAddress> initiatingPartyPersonAddresses = new ArrayList<PersonAddress>();
	private List<String> initiatingPartyPersonSSNList = new ArrayList<String>();
	public Date courtDate;
	private String ExternalCaseRecordNumber;
	//private String[] fields;
	private String custodianSSN;
	private String nonCustodianSSN;
	private TextParserFromFile oldParser = new TextParserFromFile();
	
	us.gaje.ocss.stars.DataFile dataFile;
	
	/**
	 * Constructor
	 * 
	 * @throws ParseException
	 * @throws IOException
	 */
	public ValidatingTextFile() {
		
	}

	/**
	 * @param field
	 * @return
	 */
	private boolean validateChild(String field) {
		int index = field.indexOf(" ");
		LOG.info("The index is .." + index);
		if (index == -1 && field.length() > 1) {
			LOG.info("There is no space in the child field..");
			return false;
		} else {
			LOG.info("There is space in the child field...");
			return true;
		}
	}

	/**
	 * @param field
	 * @return
	 */
	private boolean validateFirstOrLastOrSuffix(String field) {
		if (field.contains("/")) {
			return false;
		} else {
			return true;
		}

	}

	/**
	 * the validatePerson method checks if the fields for the first , middle,
	 * last, and suffix contain all letters or are null
	 */
	private boolean validatePerson(String firstName, String middleName,
			String lastName, String suffixName) {
		LOG.info("Inside the validation of a person...");
		boolean f = validateFirstOrLastOrSuffix(firstName);
		boolean m;
		boolean s;
		if (middleName == null) {
			m = true;
		} else {
			m = validateFirstOrLastOrSuffix(middleName);
		}
		boolean l = validateFirstOrLastOrSuffix(lastName);
		if (suffixName == null) {
			s = true;
		} else {
			s = validateFirstOrLastOrSuffix(suffixName);
		}
		if (f && m && l && s) {
			LOG.info("The person field is valid...");
			return true;
		} else {
			LOG.info("The validatePerson method returns false...");
			return false;
		}
	}

	/**
	 * @param personAttorney
	 * @return
	 */
	public boolean validateAttorney(Person personAttorney) {
		return false;
	}

	/**
	 * @return
	 */
	public Person getCusPerson() {
		return cusPerson;
	}

	/**
	 * 
	 * @param cusPerson
	 */
	public void setCusPerson(Person cusPerson) {
		this.cusPerson = cusPerson;
	}

	/**
	 * Getter for cuspersonAddress
	 * 
	 * @return
	 */
	public PersonAddress getCusPersonAddress() {
		return cusPersonAddress;
	}

	/**
	 * @param cusPersonAddress
	 */
	public void setCusPersonAddress(PersonAddress cusPersonAddress) {
		this.cusPersonAddress = cusPersonAddress;
	}

	/*
	 * Getter for cuspersonAddress
	 * 
	 * @return
	 *
	public Address getCusPersonAddress() {
		return cusPersonAddress;
	}

	/*
	 * @param cusPersonAddress
	 *
	public void setCusPersonAddress(Address cusPersonAddress) {
		this.cusPersonAddress = cusPersonAddress;
	}
	*/
	/**
	 * @return
	 */
	public Person getNonCusPerson() {
		return nonCusPerson;
	}

	/**
	 * @param nonCusPerson
	 */
	public void setNonCusPerson(Person nonCusPerson) {
		this.nonCusPerson = nonCusPerson;
	}

	/**
	 * @return
	 */
	public PersonAddress getNonCusPersonAddress() {
		return nonCusPersonAddress;
	}

	/**
	 * @param nonCusPersonAddress
	 */
	public void setNonCusPersonAddress(PersonAddress nonCusPersonAddress) {
		this.nonCusPersonAddress = nonCusPersonAddress;
	}

	/*
	 * @return
	 *
	public Address getNonCusPersonAddress() {
		return nonCusPersonAddress;
	}

	/*
	 * @param nonCusPersonAddress
	 *
	public void setNonCusPersonAddress(Address nonCusPersonAddress) {
		this.nonCusPersonAddress = nonCusPersonAddress;
	}
*/
	/**
	 * @return
	 */
	public List<Person> getInitiatingPartyPersonsList() {
		return initiatingPartyPersonsList;
	}

	/**
	 * @param initiatingPartyPersonsList
	 */
	public void setInitiatingPartyPersonsList(
			List<Person> initiatingPartyPersonsList) {
		this.initiatingPartyPersonsList = initiatingPartyPersonsList;
	}

	/**
	 * @return
	 */
	public List<PersonAddress> getInitiatingPartyPersonAddresses() {
		return initiatingPartyPersonAddresses;
	}

	/**
	 * @param initiatingPartyPersonAddresses
	 */
	public void setInitiatingPartyPersonAddresses(
			List<PersonAddress> initiatingPartyPersonAddresses) {
		this.initiatingPartyPersonAddresses = initiatingPartyPersonAddresses;
	}

	/**
	 * @return
	 */
	public Date getCourtDate() {
		return courtDate;
	}

	/**
	 * @param courtDate
	 */
	/**
	 * @param courtDate
	 */
	public void setCourtDate(Date courtDate) {
		this.courtDate = courtDate;
	}

	/**
	 * @return
	 */
	public String getExternalCaseRecordNumber() {
		return ExternalCaseRecordNumber;
	}

	/**
	 * @param externalCaseRecordNumber
	 */
	public void setExternalCaseRecordNumber(String externalCaseRecordNumber) {
		ExternalCaseRecordNumber = externalCaseRecordNumber;
	}

	/**
	 * @return
	 */
	public List<String> getInitiatingPartyPersonSSNList() {
		return initiatingPartyPersonSSNList;
	}

	/**
	 * @param initiatingPartyPersonSSNList
	 */
	public void setInitiatingPartyPersonSSNList(
			List<String> initiatingPartyPersonSSNList) {
		this.initiatingPartyPersonSSNList = initiatingPartyPersonSSNList;
	}

	/**
	 * @return the fields
	 */
	/*
	public String[] getFields() {
		return fields;
	}
	*/

	/**
	 * @param fields
	 *            the fields to set
	 */
	/*
	public void setFields(String[] fields) {
		this.fields = fields;
	}
	*/

	/**
	 * @return the custodianSSN
	 */
	public String getCustodianSSN() {
		return custodianSSN;
	}

	/**
	 * @param custodianSSN
	 *            the custodianSSN to set
	 */
	public void setCustodianSSN(String custodianSSN) {
		this.custodianSSN = custodianSSN;
	}

	/**
	 * @return the nonCustodianSSN
	 */
	public String getNonCustodianSSN() {
		return nonCustodianSSN;
	}

	/**
	 * @param nonCustodianSSN
	 *            the nonCustodianSSN to set
	 */
	public void setNonCustodianSSN(String nonCustodianSSN) {
		this.nonCustodianSSN = nonCustodianSSN;
	}

	/**
	 * @return the cusAddress
	 */
	public Address getCusAddress() {
		return cusAddress;
	}

	/**
	 * @param cusAddress the cusAddress to set
	 */
	public void setCusAddress(Address cusAddress) {
		this.cusAddress = cusAddress;
	}

	/**
	 * @return the nonCusAddress
	 */
	public Address getNonCusAddress() {
		return nonCusAddress;
	}

	/**
	 * @param nonCusAddress the nonCusAddress to set
	 */
	public void setNonCusAddress(Address nonCusAddress) {
		this.nonCusAddress = nonCusAddress;
	}
	//the following two methods are to be used in the near future
	/*
	public boolean validatePersonFromDataFile(int fieldNumber){
		NameValidator val = new NameValidator();
		boolean first = val.isFirstOrLastNameValid(this.fields[fieldNumber]);
		boolean middle = val.isMiddleNameValid(this.fields[fieldNumber+1]);
		boolean last = val.isFirstOrLastNameValid(this.fields[fieldNumber+2]);
		boolean suffix = val.isMiddleNameValid(this.fields[fieldNumber+3]);
		if(first && middle && last && last){
			return true;
		}else{
			return false;
		}
	}
	*/
	/*
	public Person extractPersonFromDataFile(int fieldNumber){
		Person person = new Person();
		boolean isPersonValid = validatePersonFromDataFile(fieldNumber);
		if(isPersonValid){
			person.setFirstName(this.fields[fieldNumber]);
			person.setMiddleName(this.fields[fieldNumber+1]);
			person.setLastName(this.fields[fieldNumber+2]);
			person.setSuffixName(this.fields[fieldNumber+3]);
			return person;
		}else{
			return null;
		}
	}
	*/
		

	/**
	 * @param inStream
	 * @return
	 * @throws Exception 
	 */
	public boolean validateTextFile(InputStream inStream,int externalCaseCategoryCode) throws Exception {
		boolean firstChild = false;
		//String[] arrayOfText = parser.textFileToStringArray(inStream);
		
		this.dataFile = DataFile.loadDataFile(new InputStreamReader(inStream));
		
		courtDate = DateUtil.convertStringToDate(this.dataFile.COURT_DATE());
		
		//this.fields = arrayOfText;
		LOG.debug("About to extract ssn for first child . . . ");
		// String firstSSN = extractFieldValue(153);
		String firstSSN = this.dataFile.CHILD1_SSN();
		LOG.debug("About to extract ssn for second child . . . ");
		String secondSSN = this.dataFile.CHILD2_SSN();
		LOG.debug("About to extract ssn for third child . . . ");
		String thirdSSN = this.dataFile.CHILD3_SSN();
		LOG.debug("About to extract ssn for fourth child . . . ");
		String fourthSSN = this.dataFile.CHILD4_SSN();
		LOG.debug("About to extract ssn for fifth child . . . ");
		String fifthSSN = this.dataFile.CHILD5_SSN();
		LOG.debug("About to extract ssn for sixth child . . . ");
		String sixthSSN = this.dataFile.CHILD6_SSN();
		LOG.debug("About to extract dob for first child . . . ");
		String firstDoB = this.dataFile.CHILD1_DATE_OF_BIRTH();
		LOG.debug("About to extract dob for second child . . . ");
		String secondDoB = this.dataFile.CHILD2_DATE_OF_BIRTH();
		LOG.debug("About to extract dob for third child . . . ");
		String thirdDoB = this.dataFile.CHILD3_DATE_OF_BIRTH();
		LOG.debug("About to extract dob for fourth child . . . ");
		String fourthDoB = this.dataFile.CHILD4_DATE_OF_BIRTH();
		LOG.debug("About to extract dob for fifth child . . . ");
		String fifthDoB = this.dataFile.CHILD5_DATE_OF_BIRTH();
		LOG.debug("About to extract dob for sixth child . . . ");
		String sixthDoB = this.dataFile.CHILD6_DATE_OF_BIRTH();
		this.setExternalCaseRecordNumber(this.dataFile.CASE_NUMBER());				
		this.setCustodianSSN(this.dataFile.CP_SOCIAL_SECURITY_NUMBER());
		this.setNonCustodianSSN(this.dataFile.NCP_SOCIAL_SECURITY_NUMBER());
		boolean custodian = validatePerson(
				this.dataFile.CP_FIRST_NAME(),
				this.dataFile.CP_MIDDLE_NAME(),
				this.dataFile.CP_LAST_NAME(),
				this.dataFile.CP_SUFFIX_NAME());
		
		if (custodian) {

			this.setCusPerson(oldParser
					.populatePersonInfoUsingMultiFieldNameFormat(
							this.dataFile.CP_FIRST_NAME(),//.substring(1),TODO: someone say why substring was here?
							this.dataFile.CP_MIDDLE_NAME(), 
							this.dataFile.CP_LAST_NAME(),
							this.dataFile.CP_SUFFIX_NAME(), 
							this.dataFile.CP_DATE_OF_BIRTH()));
			
			this.setCusAddress(oldParser
					.populatePersonInfoAddress(
							this.dataFile.CP_ADDRESS_LINE1(),
							this.dataFile.CP_ADDRESS_LINE2(),
							this.dataFile.CP_ADDRESS_CITY(),
							this.dataFile.CP_ADDRESS_STATE(),
							this.dataFile.CP_ADDRESS_ZIP()));							
			int addressCategoryCode = 1;	//for physical address
			int addressTypeCode = 1;	//for primary address
			AddressCategory addressCategory = this.getModelFacade().findAddressCateory(addressCategoryCode);
			AddressType addressType = this.getModelFacade().findAddressType(addressTypeCode, addressCategory);
			this.setCusPersonAddress(this.getPersonAddress(this.getCusAddress(),this.getCusPerson(),addressType));
		}
		boolean nonCustodian = validatePerson(
				this.dataFile.NCP_FIRST_NAME(),
				this.dataFile.NCP_MIDDLE_NAME(),
				this.dataFile.NCP_LAST_NAME(),
				this.dataFile.NCP_SUFFIX_NAME());
		if (nonCustodian) {

			this.setNonCusPerson(oldParser
					.populatePersonInfoUsingMultiFieldNameFormat(
							this.dataFile.NCP_FIRST_NAME(),
							this.dataFile.NCP_MIDDLE_NAME(),
							this.dataFile.NCP_LAST_NAME(),
							this.dataFile.NCP_SUFFIX_NAME(),
							this.dataFile.NCP_DATE_OF_BIRTH()));

			this.setNonCusAddress(oldParser
					.populatePersonInfoAddress(
							this.dataFile.NCP_ADDRESS_LINE1(),
							this.dataFile.NCP_ADDRESS_LINE2(),
							this.dataFile.NCP_ADDRESS_CITY(),
							this.dataFile.NCP_ADDRESS_STATE(),
							this.dataFile.NCP_ADDRESS_ZIP()));	
			int addressCategoryCode = 1;	//for physical address
			int addressTypeCode = 1;	//for primary address
			AddressCategory addressCategory = this.getModelFacade().findAddressCateory(addressCategoryCode);
			AddressType addressType = this.getModelFacade().findAddressType(addressTypeCode, addressCategory);
			this.setNonCusPersonAddress(this.getPersonAddress(this.getNonCusAddress(),this.getNonCusPerson(),addressType));
		}

		if(this.dataFile.CHILD1_FULL_NAME() != null && !this.dataFile.CHILD1_FULL_NAME().trim().equalsIgnoreCase(""))
		{
			firstChild = validateChild(this.dataFile.CHILD1_FULL_NAME());
			if(firstChild)
			{
				LOG.info("Inside the first child..");	
				Person firstChildP = oldParser
				.populatePersonInfoUsingSingleFieldNameFormat(
						this.dataFile.CHILD1_FULL_NAME(),
						this.dataFile.CHILD1_DATE_OF_BIRTH());
				this.initiatingPartyPersonsList.add(0, firstChildP);
				this.initiatingPartyPersonSSNList.add(0, firstSSN);
			}else{
				LOG.info("First child is invalid");
				throw new Exception("Data file is invalid!");
			}
		}else{
			if(externalCaseCategoryCode==3)
			{
				LOG.info("Has no child!");
			}else
			{
				throw new Exception("Data file is invalid!");
			}
			
			
		}
		
		if(this.dataFile.CHILD2_FULL_NAME() != null && !this.dataFile.CHILD2_FULL_NAME().trim().equalsIgnoreCase(""))
		{

			if(validateChild(this.dataFile.CHILD2_FULL_NAME()))
			{
				LOG.info("Inside the second child..");	
				Person child = oldParser
				.populatePersonInfoUsingSingleFieldNameFormat(
						this.dataFile.CHILD2_FULL_NAME(),
						this.dataFile.CHILD2_DATE_OF_BIRTH());
				this.initiatingPartyPersonsList.add(1, child);
				this.initiatingPartyPersonSSNList.add(1, secondSSN);
			}else{
				LOG.info("Second child is invalid");
			}
		}else{
			LOG.info("Has no second child");

		}
		
		if(this.dataFile.CHILD3_FULL_NAME() != null && !this.dataFile.CHILD3_FULL_NAME().trim().equalsIgnoreCase(""))
		{
			if(validateChild(this.dataFile.CHILD3_FULL_NAME()))
			{
				LOG.info("Inside the third child..");	
				Person child = oldParser
				.populatePersonInfoUsingSingleFieldNameFormat(
						this.dataFile.CHILD3_FULL_NAME(),
						this.dataFile.CHILD3_DATE_OF_BIRTH());
				this.initiatingPartyPersonsList.add(2, child);
				this.initiatingPartyPersonSSNList.add(2, thirdSSN);
			}else{
				LOG.info("third child is invalid");
			}
		}else{
			LOG.info("Has no third child");
		}
		
		if(this.dataFile.CHILD4_FULL_NAME() != null && !this.dataFile.CHILD4_FULL_NAME().trim().equalsIgnoreCase(""))
		{
			if(validateChild(this.dataFile.CHILD4_FULL_NAME()))
			{
				LOG.info("Inside the third child..");	
				Person child = oldParser
				.populatePersonInfoUsingSingleFieldNameFormat(
						this.dataFile.CHILD4_FULL_NAME(),
						this.dataFile.CHILD4_DATE_OF_BIRTH());
				this.initiatingPartyPersonsList.add(3, child);
				this.initiatingPartyPersonSSNList.add(3, fourthSSN);
			}else{
				LOG.info("fourth child is invalid");
			}
		}else{
			LOG.info("Has no fourth child");
		}
		
		if(this.dataFile.CHILD5_FULL_NAME() != null && !this.dataFile.CHILD5_FULL_NAME().trim().equalsIgnoreCase(""))
		{
			if(validateChild(this.dataFile.CHILD5_FULL_NAME()))
			{
				LOG.info("Inside the third child..");	
				Person child = oldParser
				.populatePersonInfoUsingSingleFieldNameFormat(
						this.dataFile.CHILD5_FULL_NAME(),
						this.dataFile.CHILD5_DATE_OF_BIRTH());
				this.initiatingPartyPersonsList.add(4, child);
				this.initiatingPartyPersonSSNList.add(4, fifthSSN);
			}else{
				LOG.info("fifth child is invalid");
			}
		}else{
			LOG.info("Has no fifth child");
		}
		
		if(this.dataFile.CHILD6_FULL_NAME() != null && !this.dataFile.CHILD6_FULL_NAME().trim().equalsIgnoreCase(""))
		{
			if(validateChild(this.dataFile.CHILD6_FULL_NAME()))
			{
				LOG.info("Inside the third child..");	
				Person child = oldParser
				.populatePersonInfoUsingSingleFieldNameFormat(
						this.dataFile.CHILD6_FULL_NAME(),
						this.dataFile.CHILD6_DATE_OF_BIRTH());
				this.initiatingPartyPersonsList.add(5, child);
				this.initiatingPartyPersonSSNList.add(5, sixthSSN);
			}else{
				LOG.info("sixth child is invalid");
			}
		}else{
			LOG.info("Has no sixth child");
		}
		
		if ((custodian == false) || (nonCustodian == false)	|| (firstChild == false && externalCaseCategoryCode!=3)) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * @return
	 */
	private PersonAddress getPersonAddress(Address address,Person person, AddressType addressType ) {
		PersonAddress personAddress = new PersonAddress();
		personAddress.setAddress(address);
		personAddress.setPerson(person);
		personAddress.setAddressType(addressType);
		return personAddress;
	}

	/**
	 * @return
	 * @throws IOException
	 * @throws ParseException
	 */
	/*
	public Date validateCourtDate() throws IOException, ParseException {
		this.courtDate = parser.extractCourtDate();
		return this.courtDate;
	}
	*/
	
	public ModelFacade getModelFacade() {
		return ModelFacadeHibernate.getInstance();
	}

	
	/*
	private String[] textFileToStringArray(InputStream inStream) throws IOException{
		InputStreamReader isr = new InputStreamReader(inStream);
		BufferedReader br = new BufferedReader(isr);
		String lineOfTextFile = new String();		
		String firstLine = new String();		
		firstLine = br.readLine();
		lineOfTextFile = br.readLine();
		String[] fields = lineOfTextFile.split("\",\"");
		return this.fields = fields;		
	}
	*/
		
	/*
	public String extractExternalCaseRecordNumber() throws IOException, ParseException{
		System.out.println("about to validate extenal");
		LOG.info("about to validate external");
		//String field = this.textFileToStringArray(file)[52];
		String field = fields[52];
		if(field.equalsIgnoreCase("")){
			return null;
		}else{
			return this.ExternalCaseRecordNumber = field;
		}
    }
    */
	
	/*
	public String extractCustodianSSN() throws IOException, ParseException{
		System.out.println("about to extract ssn for cus");
		String field = fields[9];
		//System.out.println("the ssn for cus is .."+field);
		if(field.equalsIgnoreCase("")){
			return null;
		}else{
			return field;
		}
    }
    */
	
	/*
	public String extractNonCustodianSSN() throws IOException, ParseException{
		System.out.println("about to extract ssn for non cus");
		String field = fields[22];
		//System.out.println("the ssn for non cus is .."+field);
		if(field.equalsIgnoreCase("")){
			return null;
		}else{
			return field;
		}
    }
    */
	/*
	public Person populatePersonInfoUsingMultiFieldNameFormat(String fName, 
			String mName, String lName, String sName, String dob) {
		Person genericPerson = new Person();
		genericPerson.setFirstName(fName);
		genericPerson.setMiddleName(mName);
		genericPerson.setLastName(lName);
		genericPerson.setSuffixName(sName);
		genericPerson.setDob(parseDateStringInMMDDYYFormat(dob));
		return genericPerson;
	}
	
	public Person populatePersonInfoUsingSingleFieldNameFormat(String fullName, 
			String dob) {
		Person genericPerson = new Person();
		genericPerson.setFirstName(extractFirstName(fullName));
		genericPerson.setMiddleName(extractMiddleName(fullName));
		genericPerson.setLastName(extractLastName(fullName));
		genericPerson.setSuffixName(extractSuffixName(fullName));
		genericPerson.setDob(parseDateStringInMMDDYYFormat(dob));
		return genericPerson;
	}
	
	public PersonAddress populatePersonInfoAddress(String fullAdd, String extenAdd, String city, String state, String zip) {
		PersonAddress cusPersonAddress = new PersonAddress();
		cusPersonAddress.setStreetFullText(fullAdd);
		cusPersonAddress.setStreetExtensionText(extenAdd);
		cusPersonAddress.setCityName(city);
		cusPersonAddress.setState(state);
		cusPersonAddress.setZipCode(zip);
		return cusPersonAddress;
	}
	*/
  
}